
#include "CTakenPriceMap.h"
#include <uam/UserAccountManager.h>
#include "../BondMarketStream.h"
#include "../QBSortVContainer.h"
#include "../BondCDCPriceInfo.h"

#ifndef _MSC_VER
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
#endif

CTakenPriceMap::CTakenPriceMap() :m_min_value(-1E5), m_with_yieldstr(false)
{

}
void CTakenPriceMap::Clear()
{
	m_prices.clear();
}
namespace{
	int CompanyIdToBrokerId(const char* companyId)
	{
		int id = atoi(companyId);
		if (CBrokerList::IsValidBroker(id))
			return id;
		char c = companyId[0];
		int corpid = c;
		return corpid;
	}
}
void CTakenPriceMap::SetMap(int ncorpid, bool withString)
{
	// 优化:避免GetLastDayMSByCorp的临时list
	m_prices.clear();
	m_clear_prices.clear();
	m_yield_prices.clear();
	int unDay = CMarketStream::GetBondDealInvalidateDay();
	

	FOR_EACH_MARKETSTREAM(unDay, it)
	{
		const MarketStreamInfo& msi = *it;
		int corpid = CompanyIdToBrokerId(msi.m_company_id);
		if ((ncorpid == 0 && CBrokerList::IsValidBroker(corpid)) ||
			ncorpid == corpid)
			SetTakenPrice(*it, withString);
	}
	

}
const char* CTakenPriceMap::GetClearPriceStr(const BrokerKey& key)
{
	static const char* blank="";
	ClearPriceMap::iterator it=m_clear_prices.find(key);
	return it!=m_clear_prices.end()?it->second.m_price:blank;
}
const char* CTakenPriceMap::GetYeildStr(const BrokerKey& key)
{
	static const char* blank = "";
	ClearPriceMap::iterator it = m_yield_prices.find(key);
	return it != m_yield_prices.end() ? it->second.m_price : blank;
}
double CTakenPriceMap::GetCleanPrice( const BrokerKey& key )
{
	PriceMap::iterator it = m_prices.find(key);
	return it != m_prices.end() ? it->second.price : 0;
}

double CTakenPriceMap::GetYield( const BrokerKey& key )
{
	PriceMap::iterator it=m_prices.find(key);
	return it!=m_prices.end()?it->second.yield:0;
}

double CTakenPriceMap::GetCleanPriceDiv( const BrokerKey& key )
{
	PriceMap::iterator it=m_prices.find(key);
	return it!=m_prices.end()?it->second.clean_price_div:0;
}

double CTakenPriceMap::GetYieldDiv( const BrokerKey& key )
{
	PriceMap::iterator it=m_prices.find(key);
	return it!=m_prices.end()?it->second.yield_div:0;
}

namespace impl{
	const char* GetYield(const MarketStreamInfo& info, const CBondInfo* pBondInfo)
	{
		if (atoi(info.m_body.m_quotetype) == 3)
			return info.m_body.m_yield;


		if (pBondInfo->IsBondABS() || pBondInfo->IsTransBond())
		{
			double ft = atof(info.m_body.m_yield);
			if (ft <= 0 || ft >= 30)
				return "";
		}
		return info.m_body.m_yield;
	}
};
bool CTakenPriceMap::SetTakenPrice( const MarketStreamInfo& msi,bool withString )
{
	// see:CSSSortBondInfo::UpdateTknPrice
	CBondInfo bi;
	int nBondIndex = -1;
	if(!CBondContainer::instance().GetBondInfoByKey(msi.m_body.m_bondkey,msi.m_body.m_listedmarket,&bi,&nBondIndex))
		return false;

	BrokerKey bkey(msi.m_company_id,nBondIndex);
	if(withString)
	{
		ClearPrice cp = {0};
		memset(&cp,0,sizeof(cp));
		memcpy(cp.m_price,msi.m_body.m_price,RTL_FIELD_SIZE(MarketStreamType2Body , m_price));
		if(m_clear_prices.find(bkey)!=m_clear_prices.end())
			return true;
		m_clear_prices[bkey]=cp;
		return true;
	}

	if(m_prices.find(bkey)!=m_prices.end())
		return true;
	TakenPrice tkprice={0};
	tkprice.price = atof(msi.m_body.m_price); //此版本调整显示成交
	tkprice.yield = atof(msi.m_body.m_yield);
	tkprice.clean_price_div=tkprice.yield_div=0;
	bool bIsCDCAuthValid = bi.IsCDCAuthValid();
	const char* pszPriceDiv = ::GetCleanPriceDiv(msi.m_body.m_cleanPrice, CBondCDCPriceInfo::instance().GetRelaEstimatePrice(bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_clean, msi.m_body.m_cleanPrice).c_str());
	if ( pszPriceDiv != nullptr && strcmp(pszPriceDiv,"--") ==0 )
	{
		tkprice.clean_price_div = m_min_value;
	}
	else
	{
		tkprice.clean_price_div = atof(pszPriceDiv);
	}

	const char* pszYieldDiv = ::GetYieldDiv(CBondCDCPriceInfo::instance().GetRelaEstimatePrice(bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, msi.m_body.m_yield).c_str(), msi.m_body.m_yield);
	if ( pszYieldDiv!=nullptr && strcmp(pszYieldDiv,"--") == 0 )
	{
		tkprice.yield_div = m_min_value;
	}
	else
	{
		tkprice.yield_div = atof(pszYieldDiv);
	}
	
	m_prices[bkey]=tkprice;

	if (m_with_yieldstr)
	{
		// 见CDlgQuoteV2::GetTakenPriceStr
		if (m_yield_prices.find(bkey) == m_yield_prices.end())
		{
			ClearPrice cp = { 0 };
			memset(&cp, 0, sizeof(cp));
			FIELDCOPY(cp.m_price, impl::GetYield(msi, &bi));
			m_yield_prices[bkey] = cp;
		}
	}
	return true;
}

double CTakenPriceMap::GetYieldCalc(const BrokerKey& key)
{
	PriceMap::iterator it = m_prices.find(key);
	if (it == m_prices.end())return 0;
	double tkn = it->second.yield;
	const CBondInfo& bi = CBondContainer::instance().ElementAtR(key.m_nIndex);
	if (bi.IsBondABS() || bi.IsTransBond())
	{
		if (tkn <= 0 || tkn >= 30)return 0;
	}
	return tkn;
}